package com.fyb.springcloud.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import javax.jws.Oneway;

/**
 * @author fyb
 * @version 1.0
 * @date 2021/3/11 11:41
 */
@Configuration
public class RedisConfig {

    //这个是 key 的生成方式,指的是我们放的 key 可以做具体的区分,不重要
    @Bean
    public KeyGenerator keyGenerator() {


        return (target,method,params)->{

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(target.getClass().getName());
            stringBuilder.append(method.getName());
            for (Object param : params) {
                stringBuilder.append(params.toString());
            }
            return stringBuilder.toString();

        };
    }
    //,不重要,指的是我们缓存的写入方式
    @Bean
    public CacheManager cacheManager(LettuceConnectionFactory connectionFactory) {
        //以锁写入的方式创建我们的写入对象
        RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(connectionFactory);
        //创建默认的缓存配置对象
        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        //根据我们的默认配置和写入方式创建缓存的管理器
        RedisCacheManager manager = new RedisCacheManager(writer, cacheConfiguration);

        return manager;
    }

    @Bean
    public RedisTemplate<String,Object> template(LettuceConnectionFactory factory){
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory); //设置需要来连接 的redis

        //设置key  的序列化方式

        //创建一个字符串的序列化方式,所有的数据会被序列为字符串
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        //设置key的序列化方式为字符串
        redisTemplate.setKeySerializer(stringRedisSerializer);
        //设置hash的序列化方式为字符串
        redisTemplate.setHashKeySerializer(stringRedisSerializer);

        //设置value 的序列化方式

        //创建一个解析的json的序列化对象
        Jackson2JsonRedisSerializer jsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //因为 jackson 中是使用ObjectMapper来进行序列化的,所以我们需要设置给ObjectMapper
        ObjectMapper objectMapper= new ObjectMapper();

        //设置所有非 final 修饰的变量都可以被序列化
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        //指定我们的objectMapper
        jsonRedisSerializer.setObjectMapper(objectMapper);

        //设置value 的序列化方式 //设置值的序列化方式为 json
        redisTemplate.setValueSerializer(jsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jsonRedisSerializer);
        redisTemplate.afterPropertiesSet();

        return redisTemplate;

    }
}
